#ifndef BUST_DELEGATE_H
#define BUST_DELEGATE_H

namespace bust
{

class GenericClass;

template <typename Signature>
class delegate;

template <typename Ret>
class delegate<Ret ()>
{
private:
  typedef Ret (*freeFuncPtr)();
  typedef Ret (GenericClass::*genericMemFn)();
public:
  typedef Ret result_type;

  //! @brief Create empty delegate.
  delegate()
  {
    clear();
  }
  //! @brief Bind free function.
  delegate(freeFuncPtr fn)
  {
    bind(fn);
  }
  //! @brief Bind non-const member function.
  template <typename X, typename Y>
  delegate(Y* obj, Ret (X::*fn)())
  {
    bind(obj, fn);
  }
  //! @brief Bind const member function.
  template <typename X, typename Y>
  delegate(const Y* obj, Ret (X::*fn)() const)
  {
    bind(obj, fn);
  }

  // Default copy constructor and assignment operator are fine.

  //! @brief Bind free function.
  delegate<Ret ()>& operator=(freeFuncPtr fn)
  {
    bind(fn);
    return *this;
  }

  //! @brief Bind free function.
  void bind(freeFuncPtr fn)
  {
    staticFunction = fn;
    invoker = &staticFuncInvoker;
  }
  //! @brief Bind non-const member function.
  template <typename X, typename Y>
  void bind(Y* obj, Ret (X::*fn)())
  {
    pObj = reinterpret_cast<GenericClass*>(static_cast<X*>(obj));
    void* tmp = &function;
    *static_cast<Ret (X::**)()>(tmp) = fn;
    invoker = &memberFuncInvoker<X>;
  }
  //! @brief Bind const member function.
  template <typename X, typename Y>
  void bind(const Y* obj, Ret (X::*fn)() const)
  {
    pObj = const_cast<GenericClass*>(reinterpret_cast<const GenericClass*>(static_cast<const X*>(obj)));
    void* tmp = &function;
    *static_cast<Ret (X::**)() const>(tmp) = fn;
    invoker = &memberFuncInvoker<X>;
  }
  //! @brief Clear delegate.
  void clear()
  {
    invoker = 0;
  }

  //! @brief Invoke delegate.
  Ret operator()() const
  {
    return invoker(this);
  }

  //! @brief Returns @c true if delegate is empty, @c false otherwise.
  bool empty() const
  {
    return invoker == 0;
  }
  //! @brief Returns @c true if delegate is empty, @c false otherwise.
  bool operator!() const
  {
    return empty();
  }
private:
  struct SafeBoolStruct
  {
    int foo;
    freeFuncPtr nonzero;
  };
  typedef freeFuncPtr SafeBoolStruct::* unspecified_bool_type;
public:
  //! @brief Safe bool trick.
  operator unspecified_bool_type() const
  {
    return empty() ? 0 : &SafeBoolStruct::nonzero;
  }

  //! @brief Check for equality.
  friend bool operator==(const delegate<Ret ()>& lhs, const delegate<Ret ()>& rhs)
  {
    typedef delegate<Ret ()> delegate;
    
    if(lhs.invoker == &delegate::staticFuncInvoker && rhs.invoker == &delegate::staticFuncInvoker)
      return lhs.staticFunction == rhs.staticFunction;
    else
      return lhs.pObj == rhs.pObj && lhs.function == rhs.function;
  }
  //! @brief Check for inequality
  friend bool operator!=(const delegate<Ret ()>& lhs, const delegate<Ret ()>& rhs)
  {
    return !(lhs == rhs);
  }

private:
  GenericClass* pObj;
  Ret (*invoker)(const delegate<Ret ()>*);
  union
  {
    genericMemFn function;
    freeFuncPtr staticFunction;
  };

  static Ret staticFuncInvoker(const delegate<Ret ()>* pThis)
  {
    return pThis->staticFunction();
  }

  template <typename T>
  static Ret memberFuncInvoker(const delegate<Ret ()>* pThis)
  {
    T* obj = reinterpret_cast<T*>(pThis->pObj);
    const void* tmp = &pThis->function;
    Ret (T::*mfp)() = *static_cast<Ret (T::* const*)()>(tmp);
    return (obj->*mfp)();
  }
};



template <typename Ret, typename A1>
class delegate<Ret (A1)>
{
private:
  typedef Ret (*freeFuncPtr)(A1);
  typedef Ret (GenericClass::*genericMemFn)(A1);
public:
  typedef Ret result_type;

  //! @brief Create empty delegate.
  delegate()
  {
    clear();
  }
  //! @brief Bind free function.
  delegate(freeFuncPtr fn)
  {
    bind(fn);
  }
  //! @brief Bind non-const member function.
  template <typename X, typename Y>
  delegate(Y* obj, Ret (X::*fn)(A1))
  {
    bind(obj, fn);
  }
  //! @brief Bind const member function.
  template <typename X, typename Y>
  delegate(const Y* obj, Ret (X::*fn)(A1) const)
  {
    bind(obj, fn);
  }

  // Default copy constructor and assignment operator are fine.

  //! @brief Bind free function.
  delegate<Ret (A1)>& operator=(freeFuncPtr fn)
  {
    bind(fn);
    return *this;
  }

  //! @brief Bind free function.
  void bind(freeFuncPtr fn)
  {
    staticFunction = fn;
    invoker = &staticFuncInvoker;
  }
  //! @brief Bind non-const member function.
  template <typename X, typename Y>
  void bind(Y* obj, Ret (X::*fn)(A1))
  {
    pObj = reinterpret_cast<GenericClass*>(static_cast<X*>(obj));
    void* tmp = &function;
    *static_cast<Ret (X::**)(A1)>(tmp) = fn;
    invoker = &memberFuncInvoker<X>;
  }
  //! @brief Bind const member function.
  template <typename X, typename Y>
  void bind(const Y* obj, Ret (X::*fn)(A1) const)
  {
    pObj = const_cast<GenericClass*>(reinterpret_cast<const GenericClass*>(static_cast<const X*>(obj)));
    void* tmp = &function;
    *static_cast<Ret (X::**)(A1) const>(tmp) = fn;
    invoker = &memberFuncInvoker<X>;
  }
  //! @brief Clear delegate.
  void clear()
  {
    invoker = 0;
  }

  //! @brief Invoke delegate.
  Ret operator()(A1 a1) const
  {
    return invoker(this, a1);
  }

  //! @brief Returns @c true if delegate is empty, @c false otherwise.
  bool empty() const
  {
    return invoker == 0;
  }
  //! @brief Returns @c true if delegate is empty, @c false otherwise.
  bool operator!() const
  {
    return empty();
  }
private:
  struct SafeBoolStruct
  {
    int foo;
    freeFuncPtr nonzero;
  };
  typedef freeFuncPtr SafeBoolStruct::* unspecified_bool_type;
public:
  //! @brief Safe bool trick.
  operator unspecified_bool_type() const
  {
    return empty() ? 0 : &SafeBoolStruct::nonzero;
  }

  //! @brief Check for equality.
  friend bool operator==(const delegate<Ret (A1)>& lhs, const delegate<Ret (A1)>& rhs)
  {
    typedef delegate<Ret (A1)> delegate;
    
    if(lhs.invoker == &delegate::staticFuncInvoker && rhs.invoker == &delegate::staticFuncInvoker)
      return lhs.staticFunction == rhs.staticFunction;
    else
      return lhs.pObj == rhs.pObj && lhs.function == rhs.function;
  }
  //! @brief Check for inequality
  friend bool operator!=(const delegate<Ret (A1)>& lhs, const delegate<Ret (A1)>& rhs)
  {
    return !(lhs == rhs);
  }

private:
  GenericClass* pObj;
  Ret (*invoker)(const delegate<Ret (A1)>*, A1);
  union
  {
    genericMemFn function;
    freeFuncPtr staticFunction;
  };

  static Ret staticFuncInvoker(const delegate<Ret (A1)>* pThis, A1 a1)
  {
    return pThis->staticFunction(a1);
  }

  template <typename T>
  static Ret memberFuncInvoker(const delegate<Ret (A1)>* pThis, A1 a1)
  {
    T* obj = reinterpret_cast<T*>(pThis->pObj);
    const void* tmp = &pThis->function;
    Ret (T::*mfp)(A1) = *static_cast<Ret (T::* const*)(A1)>(tmp);
    return (obj->*mfp)(a1);
  }
};


template <typename Ret, typename A1, typename A2>
class delegate<Ret (A1, A2)>
{
private:
  typedef Ret (*freeFuncPtr)(A1, A2);
  typedef Ret (GenericClass::*genericMemFn)(A1, A2);
public:
  typedef Ret result_type;

  //! @brief Create empty delegate.
  delegate()
  {
    clear();
  }
  //! @brief Bind free function.
  delegate(freeFuncPtr fn)
  {
    bind(fn);
  }
  //! @brief Bind non-const member function.
  template <typename X, typename Y>
  delegate(Y* obj, Ret (X::*fn)(A1, A2))
  {
    bind(obj, fn);
  }
  //! @brief Bind const member function.
  template <typename X, typename Y>
  delegate(const Y* obj, Ret (X::*fn)(A1, A2) const)
  {
    bind(obj, fn);
  }

  // Default copy constructor and assignment operator are fine.

  //! @brief Bind free function.
  delegate<Ret (A1, A2)>& operator=(freeFuncPtr fn)
  {
    bind(fn);
    return *this;
  }

  //! @brief Bind free function.
  void bind(freeFuncPtr fn)
  {
    staticFunction = fn;
    invoker = &staticFuncInvoker;
  }
  //! @brief Bind non-const member function.
  template <typename X, typename Y>
  void bind(Y* obj, Ret (X::*fn)(A1, A2))
  {
    pObj = reinterpret_cast<GenericClass*>(static_cast<X*>(obj));
    void* tmp = &function;
    *static_cast<Ret (X::**)(A1, A2)>(tmp) = fn;
    invoker = &memberFuncInvoker<X>;
  }
  //! @brief Bind const member function.
  template <typename X, typename Y>
  void bind(const Y* obj, Ret (X::*fn)(A1, A2) const)
  {
    pObj = const_cast<GenericClass*>(reinterpret_cast<const GenericClass*>(static_cast<const X*>(obj)));
    void* tmp = &function;
    *static_cast<Ret (X::**)(A1, A2) const>(tmp) = fn;
    invoker = &memberFuncInvoker<X>;
  }
  //! @brief Clear delegate.
  void clear()
  {
    invoker = 0;
  }

  //! @brief Invoke delegate.
  Ret operator()(A1 a1, A2 a2) const
  {
    return invoker(this, a1, a2);
  }

  //! @brief Returns @c true if delegate is empty, @c false otherwise.
  bool empty() const
  {
    return invoker == 0;
  }
  //! @brief Returns @c true if delegate is empty, @c false otherwise.
  bool operator!() const
  {
    return empty();
  }
private:
  struct SafeBoolStruct
  {
    int foo;
    freeFuncPtr nonzero;
  };
  typedef freeFuncPtr SafeBoolStruct::* unspecified_bool_type;
public:
  //! @brief Safe bool trick.
  operator unspecified_bool_type() const
  {
    return empty() ? 0 : &SafeBoolStruct::nonzero;
  }

  //! @brief Check for equality.
  friend bool operator==(const delegate<Ret (A1, A2)>& lhs, const delegate<Ret (A1, A2)>& rhs)
  {
    typedef delegate<Ret (A1, A2)> delegate;
    
    if(lhs.invoker == &delegate::staticFuncInvoker && rhs.invoker == &delegate::staticFuncInvoker)
      return lhs.staticFunction == rhs.staticFunction;
    else
      return lhs.pObj == rhs.pObj && lhs.function == rhs.function;
  }
  //! @brief Check for inequality
  friend bool operator!=(const delegate<Ret (A1, A2)>& lhs, const delegate<Ret (A1, A2)>& rhs)
  {
    return !(lhs == rhs);
  }

private:
  GenericClass* pObj;
  Ret (*invoker)(const delegate<Ret (A1, A2)>*, A1, A2);
  union
  {
    genericMemFn function;
    freeFuncPtr staticFunction;
  };

  static Ret staticFuncInvoker(const delegate<Ret (A1, A2)>* pThis, A1 a1, A2 a2)
  {
    return pThis->staticFunction(a1, a2);
  }

  template <typename T>
  static Ret memberFuncInvoker(const delegate<Ret (A1, A2)>* pThis, A1 a1, A2 a2)
  {
    T* obj = reinterpret_cast<T*>(pThis->pObj);
    const void* tmp = &pThis->function;
    Ret (T::*mfp)(A1, A2) = *static_cast<Ret (T::* const*)(A1, A2)>(tmp);
    return (obj->*mfp)(a1, a2);
  }
};


template <typename Ret, typename A1, typename A2, typename A3>
class delegate<Ret (A1, A2, A3)>
{
private:
  typedef Ret (*freeFuncPtr)(A1, A2, A3);
  typedef Ret (GenericClass::*genericMemFn)(A1, A2, A3);
public:
  typedef Ret result_type;

  //! @brief Create empty delegate.
  delegate()
  {
    clear();
  }
  //! @brief Bind free function.
  delegate(freeFuncPtr fn)
  {
    bind(fn);
  }
  //! @brief Bind non-const member function.
  template <typename X, typename Y>
  delegate(Y* obj, Ret (X::*fn)(A1, A2, A3))
  {
    bind(obj, fn);
  }
  //! @brief Bind const member function.
  template <typename X, typename Y>
  delegate(const Y* obj, Ret (X::*fn)(A1, A2, A3) const)
  {
    bind(obj, fn);
  }

  // Default copy constructor and assignment operator are fine.

  //! @brief Bind free function.
  delegate<Ret (A1, A2, A3)>& operator=(freeFuncPtr fn)
  {
    bind(fn);
    return *this;
  }

  //! @brief Bind free function.
  void bind(freeFuncPtr fn)
  {
    staticFunction = fn;
    invoker = &staticFuncInvoker;
  }
  //! @brief Bind non-const member function.
  template <typename X, typename Y>
  void bind(Y* obj, Ret (X::*fn)(A1, A2, A3))
  {
    pObj = reinterpret_cast<GenericClass*>(static_cast<X*>(obj));
    void* tmp = &function;
    *static_cast<Ret (X::**)(A1, A2, A3)>(tmp) = fn;
    invoker = &memberFuncInvoker<X>;
  }
  //! @brief Bind const member function.
  template <typename X, typename Y>
  void bind(const Y* obj, Ret (X::*fn)(A1, A2, A3) const)
  {
    pObj = const_cast<GenericClass*>(reinterpret_cast<const GenericClass*>(static_cast<const X*>(obj)));
    void* tmp = &function;
    *static_cast<Ret (X::**)(A1, A2, A3) const>(tmp) = fn;
    invoker = &memberFuncInvoker<X>;
  }
  //! @brief Clear delegate.
  void clear()
  {
    invoker = 0;
  }

  //! @brief Invoke delegate.
  Ret operator()(A1 a1, A2 a2, A3 a3) const
  {
    return invoker(this, a1, a2, a3);
  }

  //! @brief Returns @c true if delegate is empty, @c false otherwise.
  bool empty() const
  {
    return invoker == 0;
  }
  //! @brief Returns @c true if delegate is empty, @c false otherwise.
  bool operator!() const
  {
    return empty();
  }
private:
  struct SafeBoolStruct
  {
    int foo;
    freeFuncPtr nonzero;
  };
  typedef freeFuncPtr SafeBoolStruct::* unspecified_bool_type;
public:
  //! @brief Safe bool trick.
  operator unspecified_bool_type() const
  {
    return empty() ? 0 : &SafeBoolStruct::nonzero;
  }

  //! @brief Check for equality.
  friend bool operator==(const delegate<Ret (A1, A2, A3)>& lhs, const delegate<Ret (A1, A2, A3)>& rhs)
  {
    typedef delegate<Ret (A1, A2, A3)> delegate;
    
    if(lhs.invoker == &delegate::staticFuncInvoker && rhs.invoker == &delegate::staticFuncInvoker)
      return lhs.staticFunction == rhs.staticFunction;
    else
      return lhs.pObj == rhs.pObj && lhs.function == rhs.function;
  }
  //! @brief Check for inequality
  friend bool operator!=(const delegate<Ret (A1, A2, A3)>& lhs, const delegate<Ret (A1, A2, A3)>& rhs)
  {
    return !(lhs == rhs);
  }

private:
  GenericClass* pObj;
  Ret (*invoker)(const delegate<Ret (A1, A2, A3)>*, A1, A2, A3);
  union
  {
    genericMemFn function;
    freeFuncPtr staticFunction;
  };

  static Ret staticFuncInvoker(const delegate<Ret (A1, A2, A3)>* pThis, A1 a1, A2 a2, A3 a3)
  {
    return pThis->staticFunction(a1, a2, a3);
  }

  template <typename T>
  static Ret memberFuncInvoker(const delegate<Ret (A1, A2, A3)>* pThis, A1 a1, A2 a2, A3 a3)
  {
    T* obj = reinterpret_cast<T*>(pThis->pObj);
    const void* tmp = &pThis->function;
    Ret (T::*mfp)(A1, A2, A3) = *static_cast<Ret (T::* const*)(A1, A2, A3)>(tmp);
    return (obj->*mfp)(a1, a2, a3);
  }
};


template <typename Ret, typename A1, typename A2, typename A3, typename A4>
class delegate<Ret (A1, A2, A3, A4)>
{
private:
  typedef Ret (*freeFuncPtr)(A1, A2, A3, A4);
  typedef Ret (GenericClass::*genericMemFn)(A1, A2, A3, A4);
public:
  typedef Ret result_type;

  //! @brief Create empty delegate.
  delegate()
  {
    clear();
  }
  //! @brief Bind free function.
  delegate(freeFuncPtr fn)
  {
    bind(fn);
  }
  //! @brief Bind non-const member function.
  template <typename X, typename Y>
  delegate(Y* obj, Ret (X::*fn)(A1, A2, A3, A4))
  {
    bind(obj, fn);
  }
  //! @brief Bind const member function.
  template <typename X, typename Y>
  delegate(const Y* obj, Ret (X::*fn)(A1, A2, A3, A4) const)
  {
    bind(obj, fn);
  }

  // Default copy constructor and assignment operator are fine.

  //! @brief Bind free function.
  delegate<Ret (A1, A2, A3, A4)>& operator=(freeFuncPtr fn)
  {
    bind(fn);
    return *this;
  }

  //! @brief Bind free function.
  void bind(freeFuncPtr fn)
  {
    staticFunction = fn;
    invoker = &staticFuncInvoker;
  }
  //! @brief Bind non-const member function.
  template <typename X, typename Y>
  void bind(Y* obj, Ret (X::*fn)(A1, A2, A3, A4))
  {
    pObj = reinterpret_cast<GenericClass*>(static_cast<X*>(obj));
    void* tmp = &function;
    *static_cast<Ret (X::**)(A1, A2, A3, A4)>(tmp) = fn;
    invoker = &memberFuncInvoker<X>;
  }
  //! @brief Bind const member function.
  template <typename X, typename Y>
  void bind(const Y* obj, Ret (X::*fn)(A1, A2, A3, A4) const)
  {
    pObj = const_cast<GenericClass*>(reinterpret_cast<const GenericClass*>(static_cast<const X*>(obj)));
    void* tmp = &function;
    *static_cast<Ret (X::**)(A1, A2, A3, A4) const>(tmp) = fn;
    invoker = &memberFuncInvoker<X>;
  }
  //! @brief Clear delegate.
  void clear()
  {
    invoker = 0;
  }

  //! @brief Invoke delegate.
  Ret operator()(A1 a1, A2 a2, A3 a3, A4 a4) const
  {
    return invoker(this, a1, a2, a3, a4);
  }

  //! @brief Returns @c true if delegate is empty, @c false otherwise.
  bool empty() const
  {
    return invoker == 0;
  }
  //! @brief Returns @c true if delegate is empty, @c false otherwise.
  bool operator!() const
  {
    return empty();
  }
private:
  struct SafeBoolStruct
  {
    int foo;
    freeFuncPtr nonzero;
  };
  typedef freeFuncPtr SafeBoolStruct::* unspecified_bool_type;
public:
  //! @brief Safe bool trick.
  operator unspecified_bool_type() const
  {
    return empty() ? 0 : &SafeBoolStruct::nonzero;
  }

  //! @brief Check for equality.
  friend bool operator==(const delegate<Ret (A1, A2, A3, A4)>& lhs, const delegate<Ret (A1, A2, A3, A4)>& rhs)
  {
    typedef delegate<Ret (A1, A2, A3, A4)> delegate;
    
    if(lhs.invoker == &delegate::staticFuncInvoker && rhs.invoker == &delegate::staticFuncInvoker)
      return lhs.staticFunction == rhs.staticFunction;
    else
      return lhs.pObj == rhs.pObj && lhs.function == rhs.function;
  }
  //! @brief Check for inequality
  friend bool operator!=(const delegate<Ret (A1, A2, A3, A4)>& lhs, const delegate<Ret (A1, A2, A3, A4)>& rhs)
  {
    return !(lhs == rhs);
  }

private:
  GenericClass* pObj;
  Ret (*invoker)(const delegate<Ret (A1, A2, A3, A4)>*, A1, A2, A3, A4);
  union
  {
    genericMemFn function;
    freeFuncPtr staticFunction;
  };

  static Ret staticFuncInvoker(const delegate<Ret (A1, A2, A3, A4)>* pThis, A1 a1, A2 a2, A3 a3, A4 a4)
  {
    return pThis->staticFunction(a1, a2, a3, a4);
  }

  template <typename T>
  static Ret memberFuncInvoker(const delegate<Ret (A1, A2, A3, A4)>* pThis, A1 a1, A2 a2, A3 a3, A4 a4)
  {
    T* obj = reinterpret_cast<T*>(pThis->pObj);
    const void* tmp = &pThis->function;
    Ret (T::*mfp)(A1, A2, A3, A4) = *static_cast<Ret (T::* const*)(A1, A2, A3, A4)>(tmp);
    return (obj->*mfp)(a1, a2, a3, a4);
  }
};



template <typename Ret, typename A1, typename A2, typename A3, typename A4, typename A5>
class delegate<Ret (A1, A2, A3, A4, A5)>
{
private:
  typedef Ret (*freeFuncPtr)(A1, A2, A3, A4, A5);
  typedef Ret (GenericClass::*genericMemFn)(A1, A2, A3, A4, A5);
public:
  typedef Ret result_type;

  //! @brief Create empty delegate.
  delegate()
  {
    clear();
  }
  //! @brief Bind free function.
  delegate(freeFuncPtr fn)
  {
    bind(fn);
  }
  //! @brief Bind non-const member function.
  template <typename X, typename Y>
  delegate(Y* obj, Ret (X::*fn)(A1, A2, A3, A4, A5))
  {
    bind(obj, fn);
  }
  //! @brief Bind const member function.
  template <typename X, typename Y>
  delegate(const Y* obj, Ret (X::*fn)(A1, A2, A3, A4, A5) const)
  {
    bind(obj, fn);
  }

  // Default copy constructor and assignment operator are fine.

  //! @brief Bind free function.
  delegate<Ret (A1, A2, A3, A4, A5)>& operator=(freeFuncPtr fn)
  {
    bind(fn);
    return *this;
  }

  //! @brief Bind free function.
  void bind(freeFuncPtr fn)
  {
    staticFunction = fn;
    invoker = &staticFuncInvoker;
  }
  //! @brief Bind non-const member function.
  template <typename X, typename Y>
  void bind(Y* obj, Ret (X::*fn)(A1, A2, A3, A4, A5))
  {
    pObj = reinterpret_cast<GenericClass*>(static_cast<X*>(obj));
    void* tmp = &function;
    *static_cast<Ret (X::**)(A1, A2, A3, A4, A5)>(tmp) = fn;
    invoker = &memberFuncInvoker<X>;
  }
  //! @brief Bind const member function.
  template <typename X, typename Y>
  void bind(const Y* obj, Ret (X::*fn)(A1, A2, A3, A4, A5) const)
  {
    pObj = const_cast<GenericClass*>(reinterpret_cast<const GenericClass*>(static_cast<const X*>(obj)));
    void* tmp = &function;
    *static_cast<Ret (X::**)(A1, A2, A3, A4, A5) const>(tmp) = fn;
    invoker = &memberFuncInvoker<X>;
  }
  //! @brief Clear delegate.
  void clear()
  {
    invoker = 0;
  }

  //! @brief Invoke delegate.
  Ret operator()(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) const
  {
    return invoker(this, a1, a2, a3, a4, a5);
  }

  //! @brief Returns @c true if delegate is empty, @c false otherwise.
  bool empty() const
  {
    return invoker == 0;
  }
  //! @brief Returns @c true if delegate is empty, @c false otherwise.
  bool operator!() const
  {
    return empty();
  }
private:
  struct SafeBoolStruct
  {
    int foo;
    freeFuncPtr nonzero;
  };
  typedef freeFuncPtr SafeBoolStruct::* unspecified_bool_type;
public:
  //! @brief Safe bool trick.
  operator unspecified_bool_type() const
  {
    return empty() ? 0 : &SafeBoolStruct::nonzero;
  }

  //! @brief Check for equality.
  friend bool operator==(const delegate<Ret (A1, A2, A3, A4, A5)>& lhs, const delegate<Ret (A1, A2, A3, A4, A5)>& rhs)
  {
    typedef delegate<Ret (A1, A2, A3, A4, A5)> delegate;
    
    if(lhs.invoker == &delegate::staticFuncInvoker && rhs.invoker == &delegate::staticFuncInvoker)
      return lhs.staticFunction == rhs.staticFunction;
    else
      return lhs.pObj == rhs.pObj && lhs.function == rhs.function;
  }
  //! @brief Check for inequality
  friend bool operator!=(const delegate<Ret (A1, A2, A3, A4, A5)>& lhs, const delegate<Ret (A1, A2, A3, A4, A5)>& rhs)
  {
    return !(lhs == rhs);
  }

private:
  GenericClass* pObj;
  Ret (*invoker)(const delegate<Ret (A1, A2, A3, A4, A5)>*, A1, A2, A3, A4, A5);
  union
  {
    genericMemFn function;
    freeFuncPtr staticFunction;
  };

  static Ret staticFuncInvoker(const delegate<Ret (A1, A2, A3, A4, A5)>* pThis, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5)
  {
    return pThis->staticFunction(a1, a2, a3, a4, a5);
  }

  template <typename T>
  static Ret memberFuncInvoker(const delegate<Ret (A1, A2, A3, A4, A5)>* pThis, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5)
  {
    T* obj = reinterpret_cast<T*>(pThis->pObj);
    const void* tmp = &pThis->function;
    Ret (T::*mfp)(A1, A2, A3, A4, A5) = *static_cast<Ret (T::* const*)(A1, A2, A3, A4, A5)>(tmp);
    return (obj->*mfp)(a1, a2, a3, a4, a5);
  }
};



template <typename Ret, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6>
class delegate<Ret (A1, A2, A3, A4, A5, A6)>
{
private:
  typedef Ret (*freeFuncPtr)(A1, A2, A3, A4, A5, A6);
  typedef Ret (GenericClass::*genericMemFn)(A1, A2, A3, A4, A5, A6);
public:
  typedef Ret result_type;

  //! @brief Create empty delegate.
  delegate()
  {
    clear();
  }
  //! @brief Bind free function.
  delegate(freeFuncPtr fn)
  {
    bind(fn);
  }
  //! @brief Bind non-const member function.
  template <typename X, typename Y>
  delegate(Y* obj, Ret (X::*fn)(A1, A2, A3, A4, A5, A6))
  {
    bind(obj, fn);
  }
  //! @brief Bind const member function.
  template <typename X, typename Y>
  delegate(const Y* obj, Ret (X::*fn)(A1, A2, A3, A4, A5, A6) const)
  {
    bind(obj, fn);
  }

  // Default copy constructor and assignment operator are fine.

  //! @brief Bind free function.
  delegate<Ret (A1, A2, A3, A4, A5, A6)>& operator=(freeFuncPtr fn)
  {
    bind(fn);
    return *this;
  }

  //! @brief Bind free function.
  void bind(freeFuncPtr fn)
  {
    staticFunction = fn;
    invoker = &staticFuncInvoker;
  }
  //! @brief Bind non-const member function.
  template <typename X, typename Y>
  void bind(Y* obj, Ret (X::*fn)(A1, A2, A3, A4, A5, A6))
  {
    pObj = reinterpret_cast<GenericClass*>(static_cast<X*>(obj));
    void* tmp = &function;
    *static_cast<Ret (X::**)(A1, A2, A3, A4, A5, A6)>(tmp) = fn;
    invoker = &memberFuncInvoker<X>;
  }
  //! @brief Bind const member function.
  template <typename X, typename Y>
  void bind(const Y* obj, Ret (X::*fn)(A1, A2, A3, A4, A5, A6) const)
  {
    pObj = const_cast<GenericClass*>(reinterpret_cast<const GenericClass*>(static_cast<const X*>(obj)));
    void* tmp = &function;
    *static_cast<Ret (X::**)(A1, A2, A3, A4, A5, A6) const>(tmp) = fn;
    invoker = &memberFuncInvoker<X>;
  }
  //! @brief Clear delegate.
  void clear()
  {
    invoker = 0;
  }

  //! @brief Invoke delegate.
  Ret operator()(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) const
  {
    return invoker(this, a1, a2, a3, a4, a5, a6);
  }

  //! @brief Returns @c true if delegate is empty, @c false otherwise.
  bool empty() const
  {
    return invoker == 0;
  }
  //! @brief Returns @c true if delegate is empty, @c false otherwise.
  bool operator!() const
  {
    return empty();
  }
private:
  struct SafeBoolStruct
  {
    int foo;
    freeFuncPtr nonzero;
  };
  typedef freeFuncPtr SafeBoolStruct::* unspecified_bool_type;
public:
  //! @brief Safe bool trick.
  operator unspecified_bool_type() const
  {
    return empty() ? 0 : &SafeBoolStruct::nonzero;
  }

  //! @brief Check for equality.
  friend bool operator==(const delegate<Ret (A1, A2, A3, A4, A5, A6)>& lhs, const delegate<Ret (A1, A2, A3, A4, A5, A6)>& rhs)
  {
    typedef delegate<Ret (A1, A2, A3, A4, A5, A6)> delegate;
    
    if(lhs.invoker == &delegate::staticFuncInvoker && rhs.invoker == &delegate::staticFuncInvoker)
      return lhs.staticFunction == rhs.staticFunction;
    else
      return lhs.pObj == rhs.pObj && lhs.function == rhs.function;
  }
  //! @brief Check for inequality
  friend bool operator!=(const delegate<Ret (A1, A2, A3, A4, A5, A6)>& lhs, const delegate<Ret (A1, A2, A3, A4, A5, A6)>& rhs)
  {
    return !(lhs == rhs);
  }

private:
  GenericClass* pObj;
  Ret (*invoker)(const delegate<Ret (A1, A2, A3, A4, A5, A6)>*, A1, A2, A3, A4, A5, A6);
  union
  {
    genericMemFn function;
    freeFuncPtr staticFunction;
  };

  static Ret staticFuncInvoker(const delegate<Ret (A1, A2, A3, A4, A5, A6)>* pThis, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6)
  {
    return pThis->staticFunction(a1, a2, a3, a4, a5, a6);
  }

  template <typename T>
  static Ret memberFuncInvoker(const delegate<Ret (A1, A2, A3, A4, A5, A6)>* pThis, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6)
  {
    T* obj = reinterpret_cast<T*>(pThis->pObj);
    const void* tmp = &pThis->function;
    Ret (T::*mfp)(A1, A2, A3, A4, A5, A6) = *static_cast<Ret (T::* const*)(A1, A2, A3, A4, A5, A6)>(tmp);
    return (obj->*mfp)(a1, a2, a3, a4, a5, a6);
  }
};



template <typename Ret, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7>
class delegate<Ret (A1, A2, A3, A4, A5, A6, A7)>
{
private:
  typedef Ret (*freeFuncPtr)(A1, A2, A3, A4, A5, A6, A7);
  typedef Ret (GenericClass::*genericMemFn)(A1, A2, A3, A4, A5, A6, A7);
public:
  typedef Ret result_type;

  //! @brief Create empty delegate.
  delegate()
  {
    clear();
  }
  //! @brief Bind free function.
  delegate(freeFuncPtr fn)
  {
    bind(fn);
  }
  //! @brief Bind non-const member function.
  template <typename X, typename Y>
  delegate(Y* obj, Ret (X::*fn)(A1, A2, A3, A4, A5, A6, A7))
  {
    bind(obj, fn);
  }
  //! @brief Bind const member function.
  template <typename X, typename Y>
  delegate(const Y* obj, Ret (X::*fn)(A1, A2, A3, A4, A5, A6, A7) const)
  {
    bind(obj, fn);
  }

  // Default copy constructor and assignment operator are fine.

  //! @brief Bind free function.
  delegate<Ret (A1, A2, A3, A4, A5, A6, A7)>& operator=(freeFuncPtr fn)
  {
    bind(fn);
    return *this;
  }

  //! @brief Bind free function.
  void bind(freeFuncPtr fn)
  {
    staticFunction = fn;
    invoker = &staticFuncInvoker;
  }
  //! @brief Bind non-const member function.
  template <typename X, typename Y>
  void bind(Y* obj, Ret (X::*fn)(A1, A2, A3, A4, A5, A6, A7))
  {
    pObj = reinterpret_cast<GenericClass*>(static_cast<X*>(obj));
    void* tmp = &function;
    *static_cast<Ret (X::**)(A1, A2, A3, A4, A5, A6, A7)>(tmp) = fn;
    invoker = &memberFuncInvoker<X>;
  }
  //! @brief Bind const member function.
  template <typename X, typename Y>
  void bind(const Y* obj, Ret (X::*fn)(A1, A2, A3, A4, A5, A6, A7) const)
  {
    pObj = const_cast<GenericClass*>(reinterpret_cast<const GenericClass*>(static_cast<const X*>(obj)));
    void* tmp = &function;
    *static_cast<Ret (X::**)(A1, A2, A3, A4, A5, A6, A7) const>(tmp) = fn;
    invoker = &memberFuncInvoker<X>;
  }
  //! @brief Clear delegate.
  void clear()
  {
    invoker = 0;
  }

  //! @brief Invoke delegate.
  Ret operator()(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) const
  {
    return invoker(this, a1, a2, a3, a4, a5, a6, a7);
  }

  //! @brief Returns @c true if delegate is empty, @c false otherwise.
  bool empty() const
  {
    return invoker == 0;
  }
  //! @brief Returns @c true if delegate is empty, @c false otherwise.
  bool operator!() const
  {
    return empty();
  }
private:
  struct SafeBoolStruct
  {
    int foo;
    freeFuncPtr nonzero;
  };
  typedef freeFuncPtr SafeBoolStruct::* unspecified_bool_type;
public:
  //! @brief Safe bool trick.
  operator unspecified_bool_type() const
  {
    return empty() ? 0 : &SafeBoolStruct::nonzero;
  }

  //! @brief Check for equality.
  friend bool operator==(const delegate<Ret (A1, A2, A3, A4, A5, A6, A7)>& lhs, const delegate<Ret (A1, A2, A3, A4, A5, A6, A7)>& rhs)
  {
    typedef delegate<Ret (A1, A2, A3, A4, A5, A6, A7)> delegate;
    
    if(lhs.invoker == &delegate::staticFuncInvoker && rhs.invoker == &delegate::staticFuncInvoker)
      return lhs.staticFunction == rhs.staticFunction;
    else
      return lhs.pObj == rhs.pObj && lhs.function == rhs.function;
  }
  //! @brief Check for inequality
  friend bool operator!=(const delegate<Ret (A1, A2, A3, A4, A5, A6, A7)>& lhs, const delegate<Ret (A1, A2, A3, A4, A5, A6, A7)>& rhs)
  {
    return !(lhs == rhs);
  }

private:
  GenericClass* pObj;
  Ret (*invoker)(const delegate<Ret (A1, A2, A3, A4, A5, A6, A7)>*, A1, A2, A3, A4, A5, A6, A7);
  union
  {
    genericMemFn function;
    freeFuncPtr staticFunction;
  };

  static Ret staticFuncInvoker(const delegate<Ret (A1, A2, A3, A4, A5, A6, A7)>* pThis, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7)
  {
    return pThis->staticFunction(a1, a2, a3, a4, a5, a6, a7);
  }

  template <typename T>
  static Ret memberFuncInvoker(const delegate<Ret (A1, A2, A3, A4, A5, A6, A7)>* pThis, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7)
  {
    T* obj = reinterpret_cast<T*>(pThis->pObj);
    const void* tmp = &pThis->function;
    Ret (T::*mfp)(A1, A2, A3, A4, A5, A6, A7) = *static_cast<Ret (T::* const*)(A1, A2, A3, A4, A5, A6, A7)>(tmp);
    return (obj->*mfp)(a1, a2, a3, a4, a5, a6, a7);
  }
};



template <typename Ret, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8>
class delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8)>
{
private:
  typedef Ret (*freeFuncPtr)(A1, A2, A3, A4, A5, A6, A7, A8);
  typedef Ret (GenericClass::*genericMemFn)(A1, A2, A3, A4, A5, A6, A7, A8);
public:
  typedef Ret result_type;

  //! @brief Create empty delegate.
  delegate()
  {
    clear();
  }
  //! @brief Bind free function.
  delegate(freeFuncPtr fn)
  {
    bind(fn);
  }
  //! @brief Bind non-const member function.
  template <typename X, typename Y>
  delegate(Y* obj, Ret (X::*fn)(A1, A2, A3, A4, A5, A6, A7, A8))
  {
    bind(obj, fn);
  }
  //! @brief Bind const member function.
  template <typename X, typename Y>
  delegate(const Y* obj, Ret (X::*fn)(A1, A2, A3, A4, A5, A6, A7, A8) const)
  {
    bind(obj, fn);
  }

  // Default copy constructor and assignment operator are fine.

  //! @brief Bind free function.
  delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8)>& operator=(freeFuncPtr fn)
  {
    bind(fn);
    return *this;
  }

  //! @brief Bind free function.
  void bind(freeFuncPtr fn)
  {
    staticFunction = fn;
    invoker = &staticFuncInvoker;
  }
  //! @brief Bind non-const member function.
  template <typename X, typename Y>
  void bind(Y* obj, Ret (X::*fn)(A1, A2, A3, A4, A5, A6, A7, A8))
  {
    pObj = reinterpret_cast<GenericClass*>(static_cast<X*>(obj));
    void* tmp = &function;
    *static_cast<Ret (X::**)(A1, A2, A3, A4, A5, A6, A7, A8)>(tmp) = fn;
    invoker = &memberFuncInvoker<X>;
  }
  //! @brief Bind const member function.
  template <typename X, typename Y>
  void bind(const Y* obj, Ret (X::*fn)(A1, A2, A3, A4, A5, A6, A7, A8) const)
  {
    pObj = const_cast<GenericClass*>(reinterpret_cast<const GenericClass*>(static_cast<const X*>(obj)));
    void* tmp = &function;
    *static_cast<Ret (X::**)(A1, A2, A3, A4, A5, A6, A7, A8) const>(tmp) = fn;
    invoker = &memberFuncInvoker<X>;
  }
  //! @brief Clear delegate.
  void clear()
  {
    invoker = 0;
  }

  //! @brief Invoke delegate.
  Ret operator()(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) const
  {
    return invoker(this, a1, a2, a3, a4, a5, a6, a7, a8);
  }

  //! @brief Returns @c true if delegate is empty, @c false otherwise.
  bool empty() const
  {
    return invoker == 0;
  }
  //! @brief Returns @c true if delegate is empty, @c false otherwise.
  bool operator!() const
  {
    return empty();
  }
private:
  struct SafeBoolStruct
  {
    int foo;
    freeFuncPtr nonzero;
  };
  typedef freeFuncPtr SafeBoolStruct::* unspecified_bool_type;
public:
  //! @brief Safe bool trick.
  operator unspecified_bool_type() const
  {
    return empty() ? 0 : &SafeBoolStruct::nonzero;
  }

  //! @brief Check for equality.
  friend bool operator==(const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8)>& lhs, const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8)>& rhs)
  {
    typedef delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8)> delegate;
    
    if(lhs.invoker == &delegate::staticFuncInvoker && rhs.invoker == &delegate::staticFuncInvoker)
      return lhs.staticFunction == rhs.staticFunction;
    else
      return lhs.pObj == rhs.pObj && lhs.function == rhs.function;
  }
  //! @brief Check for inequality
  friend bool operator!=(const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8)>& lhs, const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8)>& rhs)
  {
    return !(lhs == rhs);
  }

private:
  GenericClass* pObj;
  Ret (*invoker)(const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8)>*, A1, A2, A3, A4, A5, A6, A7, A8);
  union
  {
    genericMemFn function;
    freeFuncPtr staticFunction;
  };

  static Ret staticFuncInvoker(const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8)>* pThis, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8)
  {
    return pThis->staticFunction(a1, a2, a3, a4, a5, a6, a7, a8);
  }

  template <typename T>
  static Ret memberFuncInvoker(const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8)>* pThis, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8)
  {
    T* obj = reinterpret_cast<T*>(pThis->pObj);
    const void* tmp = &pThis->function;
    Ret (T::*mfp)(A1, A2, A3, A4, A5, A6, A7, A8) = *static_cast<Ret (T::* const*)(A1, A2, A3, A4, A5, A6, A7, A8)>(tmp);
    return (obj->*mfp)(a1, a2, a3, a4, a5, a6, a7, a8);
  }
};



template <typename Ret, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9>
class delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9)>
{
private:
  typedef Ret (*freeFuncPtr)(A1, A2, A3, A4, A5, A6, A7, A8, A9);
  typedef Ret (GenericClass::*genericMemFn)(A1, A2, A3, A4, A5, A6, A7, A8, A9);
public:
  typedef Ret result_type;

  //! @brief Create empty delegate.
  delegate()
  {
    clear();
  }
  //! @brief Bind free function.
  delegate(freeFuncPtr fn)
  {
    bind(fn);
  }
  //! @brief Bind non-const member function.
  template <typename X, typename Y>
  delegate(Y* obj, Ret (X::*fn)(A1, A2, A3, A4, A5, A6, A7, A8, A9))
  {
    bind(obj, fn);
  }
  //! @brief Bind const member function.
  template <typename X, typename Y>
  delegate(const Y* obj, Ret (X::*fn)(A1, A2, A3, A4, A5, A6, A7, A8, A9) const)
  {
    bind(obj, fn);
  }

  // Default copy constructor and assignment operator are fine.

  //! @brief Bind free function.
  delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9)>& operator=(freeFuncPtr fn)
  {
    bind(fn);
    return *this;
  }

  //! @brief Bind free function.
  void bind(freeFuncPtr fn)
  {
    staticFunction = fn;
    invoker = &staticFuncInvoker;
  }
  //! @brief Bind non-const member function.
  template <typename X, typename Y>
  void bind(Y* obj, Ret (X::*fn)(A1, A2, A3, A4, A5, A6, A7, A8, A9))
  {
    pObj = reinterpret_cast<GenericClass*>(static_cast<X*>(obj));
    void* tmp = &function;
    *static_cast<Ret (X::**)(A1, A2, A3, A4, A5, A6, A7, A8, A9)>(tmp) = fn;
    invoker = &memberFuncInvoker<X>;
  }
  //! @brief Bind const member function.
  template <typename X, typename Y>
  void bind(const Y* obj, Ret (X::*fn)(A1, A2, A3, A4, A5, A6, A7, A8, A9) const)
  {
    pObj = const_cast<GenericClass*>(reinterpret_cast<const GenericClass*>(static_cast<const X*>(obj)));
    void* tmp = &function;
    *static_cast<Ret (X::**)(A1, A2, A3, A4, A5, A6, A7, A8, A9) const>(tmp) = fn;
    invoker = &memberFuncInvoker<X>;
  }
  //! @brief Clear delegate.
  void clear()
  {
    invoker = 0;
  }

  //! @brief Invoke delegate.
  Ret operator()(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) const
  {
    return invoker(this, a1, a2, a3, a4, a5, a6, a7, a8, a9);
  }

  //! @brief Returns @c true if delegate is empty, @c false otherwise.
  bool empty() const
  {
    return invoker == 0;
  }
  //! @brief Returns @c true if delegate is empty, @c false otherwise.
  bool operator!() const
  {
    return empty();
  }
private:
  struct SafeBoolStruct
  {
    int foo;
    freeFuncPtr nonzero;
  };
  typedef freeFuncPtr SafeBoolStruct::* unspecified_bool_type;
public:
  //! @brief Safe bool trick.
  operator unspecified_bool_type() const
  {
    return empty() ? 0 : &SafeBoolStruct::nonzero;
  }

  //! @brief Check for equality.
  friend bool operator==(const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9)>& lhs, const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9)>& rhs)
  {
    typedef delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9)> delegate;
    
    if(lhs.invoker == &delegate::staticFuncInvoker && rhs.invoker == &delegate::staticFuncInvoker)
      return lhs.staticFunction == rhs.staticFunction;
    else
      return lhs.pObj == rhs.pObj && lhs.function == rhs.function;
  }
  //! @brief Check for inequality
  friend bool operator!=(const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9)>& lhs, const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9)>& rhs)
  {
    return !(lhs == rhs);
  }

private:
  GenericClass* pObj;
  Ret (*invoker)(const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9)>*, A1, A2, A3, A4, A5, A6, A7, A8, A9);
  union
  {
    genericMemFn function;
    freeFuncPtr staticFunction;
  };

  static Ret staticFuncInvoker(const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9)>* pThis, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9)
  {
    return pThis->staticFunction(a1, a2, a3, a4, a5, a6, a7, a8, a9);
  }

  template <typename T>
  static Ret memberFuncInvoker(const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9)>* pThis, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9)
  {
    T* obj = reinterpret_cast<T*>(pThis->pObj);
    const void* tmp = &pThis->function;
    Ret (T::*mfp)(A1, A2, A3, A4, A5, A6, A7, A8, A9) = *static_cast<Ret (T::* const*)(A1, A2, A3, A4, A5, A6, A7, A8, A9)>(tmp);
    return (obj->*mfp)(a1, a2, a3, a4, a5, a6, a7, a8, a9);
  }
};



template <typename Ret, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10>
class delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)>
{
private:
  typedef Ret (*freeFuncPtr)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10);
  typedef Ret (GenericClass::*genericMemFn)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10);
public:
  typedef Ret result_type;

  //! @brief Create empty delegate.
  delegate()
  {
    clear();
  }
  //! @brief Bind free function.
  delegate(freeFuncPtr fn)
  {
    bind(fn);
  }
  //! @brief Bind non-const member function.
  template <typename X, typename Y>
  delegate(Y* obj, Ret (X::*fn)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10))
  {
    bind(obj, fn);
  }
  //! @brief Bind const member function.
  template <typename X, typename Y>
  delegate(const Y* obj, Ret (X::*fn)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10) const)
  {
    bind(obj, fn);
  }

  // Default copy constructor and assignment operator are fine.

  //! @brief Bind free function.
  delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)>& operator=(freeFuncPtr fn)
  {
    bind(fn);
    return *this;
  }

  //! @brief Bind free function.
  void bind(freeFuncPtr fn)
  {
    staticFunction = fn;
    invoker = &staticFuncInvoker;
  }
  //! @brief Bind non-const member function.
  template <typename X, typename Y>
  void bind(Y* obj, Ret (X::*fn)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10))
  {
    pObj = reinterpret_cast<GenericClass*>(static_cast<X*>(obj));
    void* tmp = &function;
    *static_cast<Ret (X::**)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)>(tmp) = fn;
    invoker = &memberFuncInvoker<X>;
  }
  //! @brief Bind const member function.
  template <typename X, typename Y>
  void bind(const Y* obj, Ret (X::*fn)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10) const)
  {
    pObj = const_cast<GenericClass*>(reinterpret_cast<const GenericClass*>(static_cast<const X*>(obj)));
    void* tmp = &function;
    *static_cast<Ret (X::**)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10) const>(tmp) = fn;
    invoker = &memberFuncInvoker<X>;
  }
  //! @brief Clear delegate.
  void clear()
  {
    invoker = 0;
  }

  //! @brief Invoke delegate.
  Ret operator()(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10) const
  {
    return invoker(this, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10);
  }

  //! @brief Returns @c true if delegate is empty, @c false otherwise.
  bool empty() const
  {
    return invoker == 0;
  }
  //! @brief Returns @c true if delegate is empty, @c false otherwise.
  bool operator!() const
  {
    return empty();
  }
private:
  struct SafeBoolStruct
  {
    int foo;
    freeFuncPtr nonzero;
  };
  typedef freeFuncPtr SafeBoolStruct::* unspecified_bool_type;
public:
  //! @brief Safe bool trick.
  operator unspecified_bool_type() const
  {
    return empty() ? 0 : &SafeBoolStruct::nonzero;
  }

  //! @brief Check for equality.
  friend bool operator==(const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)>& lhs, const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)>& rhs)
  {
    typedef delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)> delegate;
    
    if(lhs.invoker == &delegate::staticFuncInvoker && rhs.invoker == &delegate::staticFuncInvoker)
      return lhs.staticFunction == rhs.staticFunction;
    else
      return lhs.pObj == rhs.pObj && lhs.function == rhs.function;
  }
  //! @brief Check for inequality
  friend bool operator!=(const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)>& lhs, const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)>& rhs)
  {
    return !(lhs == rhs);
  }

private:
  GenericClass* pObj;
  Ret (*invoker)(const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)>*, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10);
  union
  {
    genericMemFn function;
    freeFuncPtr staticFunction;
  };

  static Ret staticFuncInvoker(const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)>* pThis, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10)
  {
    return pThis->staticFunction(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10);
  }

  template <typename T>
  static Ret memberFuncInvoker(const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)>* pThis, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10)
  {
    T* obj = reinterpret_cast<T*>(pThis->pObj);
    const void* tmp = &pThis->function;
    Ret (T::*mfp)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10) = *static_cast<Ret (T::* const*)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)>(tmp);
    return (obj->*mfp)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10);
  }
};



template <typename Ret, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11>
class delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11)>
{
private:
  typedef Ret (*freeFuncPtr)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11);
  typedef Ret (GenericClass::*genericMemFn)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11);
public:
  typedef Ret result_type;

  //! @brief Create empty delegate.
  delegate()
  {
    clear();
  }
  //! @brief Bind free function.
  delegate(freeFuncPtr fn)
  {
    bind(fn);
  }
  //! @brief Bind non-const member function.
  template <typename X, typename Y>
  delegate(Y* obj, Ret (X::*fn)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11))
  {
    bind(obj, fn);
  }
  //! @brief Bind const member function.
  template <typename X, typename Y>
  delegate(const Y* obj, Ret (X::*fn)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11) const)
  {
    bind(obj, fn);
  }

  // Default copy constructor and assignment operator are fine.

  //! @brief Bind free function.
  delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11)>& operator=(freeFuncPtr fn)
  {
    bind(fn);
    return *this;
  }

  //! @brief Bind free function.
  void bind(freeFuncPtr fn)
  {
    staticFunction = fn;
    invoker = &staticFuncInvoker;
  }
  //! @brief Bind non-const member function.
  template <typename X, typename Y>
  void bind(Y* obj, Ret (X::*fn)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11))
  {
    pObj = reinterpret_cast<GenericClass*>(static_cast<X*>(obj));
    void* tmp = &function;
    *static_cast<Ret (X::**)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11)>(tmp) = fn;
    invoker = &memberFuncInvoker<X>;
  }
  //! @brief Bind const member function.
  template <typename X, typename Y>
  void bind(const Y* obj, Ret (X::*fn)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11) const)
  {
    pObj = const_cast<GenericClass*>(reinterpret_cast<const GenericClass*>(static_cast<const X*>(obj)));
    void* tmp = &function;
    *static_cast<Ret (X::**)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11) const>(tmp) = fn;
    invoker = &memberFuncInvoker<X>;
  }
  //! @brief Clear delegate.
  void clear()
  {
    invoker = 0;
  }

  //! @brief Invoke delegate.
  Ret operator()(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11) const
  {
    return invoker(this, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11);
  }

  //! @brief Returns @c true if delegate is empty, @c false otherwise.
  bool empty() const
  {
    return invoker == 0;
  }
  //! @brief Returns @c true if delegate is empty, @c false otherwise.
  bool operator!() const
  {
    return empty();
  }
private:
  struct SafeBoolStruct
  {
    int foo;
    freeFuncPtr nonzero;
  };
  typedef freeFuncPtr SafeBoolStruct::* unspecified_bool_type;
public:
  //! @brief Safe bool trick.
  operator unspecified_bool_type() const
  {
    return empty() ? 0 : &SafeBoolStruct::nonzero;
  }

  //! @brief Check for equality.
  friend bool operator==(const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11)>& lhs, const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11)>& rhs)
  {
    typedef delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11)> delegate;
    
    if(lhs.invoker == &delegate::staticFuncInvoker && rhs.invoker == &delegate::staticFuncInvoker)
      return lhs.staticFunction == rhs.staticFunction;
    else
      return lhs.pObj == rhs.pObj && lhs.function == rhs.function;
  }
  //! @brief Check for inequality
  friend bool operator!=(const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11)>& lhs, const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11)>& rhs)
  {
    return !(lhs == rhs);
  }

private:
  GenericClass* pObj;
  Ret (*invoker)(const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11)>*, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11);
  union
  {
    genericMemFn function;
    freeFuncPtr staticFunction;
  };

  static Ret staticFuncInvoker(const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11)>* pThis, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11)
  {
    return pThis->staticFunction(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11);
  }

  template <typename T>
  static Ret memberFuncInvoker(const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11)>* pThis, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11)
  {
    T* obj = reinterpret_cast<T*>(pThis->pObj);
    const void* tmp = &pThis->function;
    Ret (T::*mfp)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11) = *static_cast<Ret (T::* const*)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11)>(tmp);
    return (obj->*mfp)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11);
  }
};



template <typename Ret, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename A12>
class delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12)>
{
private:
  typedef Ret (*freeFuncPtr)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12);
  typedef Ret (GenericClass::*genericMemFn)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12);
public:
  typedef Ret result_type;

  //! @brief Create empty delegate.
  delegate()
  {
    clear();
  }
  //! @brief Bind free function.
  delegate(freeFuncPtr fn)
  {
    bind(fn);
  }
  //! @brief Bind non-const member function.
  template <typename X, typename Y>
  delegate(Y* obj, Ret (X::*fn)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12))
  {
    bind(obj, fn);
  }
  //! @brief Bind const member function.
  template <typename X, typename Y>
  delegate(const Y* obj, Ret (X::*fn)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12) const)
  {
    bind(obj, fn);
  }

  // Default copy constructor and assignment operator are fine.

  //! @brief Bind free function.
  delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12)>& operator=(freeFuncPtr fn)
  {
    bind(fn);
    return *this;
  }

  //! @brief Bind free function.
  void bind(freeFuncPtr fn)
  {
    staticFunction = fn;
    invoker = &staticFuncInvoker;
  }
  //! @brief Bind non-const member function.
  template <typename X, typename Y>
  void bind(Y* obj, Ret (X::*fn)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12))
  {
    pObj = reinterpret_cast<GenericClass*>(static_cast<X*>(obj));
    void* tmp = &function;
    *static_cast<Ret (X::**)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12)>(tmp) = fn;
    invoker = &memberFuncInvoker<X>;
  }
  //! @brief Bind const member function.
  template <typename X, typename Y>
  void bind(const Y* obj, Ret (X::*fn)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12) const)
  {
    pObj = const_cast<GenericClass*>(reinterpret_cast<const GenericClass*>(static_cast<const X*>(obj)));
    void* tmp = &function;
    *static_cast<Ret (X::**)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12) const>(tmp) = fn;
    invoker = &memberFuncInvoker<X>;
  }
  //! @brief Clear delegate.
  void clear()
  {
    invoker = 0;
  }

  //! @brief Invoke delegate.
  Ret operator()(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12) const
  {
    return invoker(this, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12);
  }

  //! @brief Returns @c true if delegate is empty, @c false otherwise.
  bool empty() const
  {
    return invoker == 0;
  }
  //! @brief Returns @c true if delegate is empty, @c false otherwise.
  bool operator!() const
  {
    return empty();
  }
private:
  struct SafeBoolStruct
  {
    int foo;
    freeFuncPtr nonzero;
  };
  typedef freeFuncPtr SafeBoolStruct::* unspecified_bool_type;
public:
  //! @brief Safe bool trick.
  operator unspecified_bool_type() const
  {
    return empty() ? 0 : &SafeBoolStruct::nonzero;
  }

  //! @brief Check for equality.
  friend bool operator==(const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12)>& lhs, const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12)>& rhs)
  {
    typedef delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12)> delegate;
    
    if(lhs.invoker == &delegate::staticFuncInvoker && rhs.invoker == &delegate::staticFuncInvoker)
      return lhs.staticFunction == rhs.staticFunction;
    else
      return lhs.pObj == rhs.pObj && lhs.function == rhs.function;
  }
  //! @brief Check for inequality
  friend bool operator!=(const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12)>& lhs, const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12)>& rhs)
  {
    return !(lhs == rhs);
  }

private:
  GenericClass* pObj;
  Ret (*invoker)(const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12)>*, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12);
  union
  {
    genericMemFn function;
    freeFuncPtr staticFunction;
  };

  static Ret staticFuncInvoker(const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12)>* pThis, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12)
  {
    return pThis->staticFunction(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12);
  }

  template <typename T>
  static Ret memberFuncInvoker(const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12)>* pThis, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12)
  {
    T* obj = reinterpret_cast<T*>(pThis->pObj);
    const void* tmp = &pThis->function;
    Ret (T::*mfp)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12) = *static_cast<Ret (T::* const*)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12)>(tmp);
    return (obj->*mfp)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12);
  }
};



template <typename Ret, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename A12, typename A13>
class delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13)>
{
private:
  typedef Ret (*freeFuncPtr)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13);
  typedef Ret (GenericClass::*genericMemFn)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13);
public:
  typedef Ret result_type;

  //! @brief Create empty delegate.
  delegate()
  {
    clear();
  }
  //! @brief Bind free function.
  delegate(freeFuncPtr fn)
  {
    bind(fn);
  }
  //! @brief Bind non-const member function.
  template <typename X, typename Y>
  delegate(Y* obj, Ret (X::*fn)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13))
  {
    bind(obj, fn);
  }
  //! @brief Bind const member function.
  template <typename X, typename Y>
  delegate(const Y* obj, Ret (X::*fn)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13) const)
  {
    bind(obj, fn);
  }

  // Default copy constructor and assignment operator are fine.

  //! @brief Bind free function.
  delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13)>& operator=(freeFuncPtr fn)
  {
    bind(fn);
    return *this;
  }

  //! @brief Bind free function.
  void bind(freeFuncPtr fn)
  {
    staticFunction = fn;
    invoker = &staticFuncInvoker;
  }
  //! @brief Bind non-const member function.
  template <typename X, typename Y>
  void bind(Y* obj, Ret (X::*fn)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13))
  {
    pObj = reinterpret_cast<GenericClass*>(static_cast<X*>(obj));
    void* tmp = &function;
    *static_cast<Ret (X::**)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13)>(tmp) = fn;
    invoker = &memberFuncInvoker<X>;
  }
  //! @brief Bind const member function.
  template <typename X, typename Y>
  void bind(const Y* obj, Ret (X::*fn)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13) const)
  {
    pObj = const_cast<GenericClass*>(reinterpret_cast<const GenericClass*>(static_cast<const X*>(obj)));
    void* tmp = &function;
    *static_cast<Ret (X::**)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13) const>(tmp) = fn;
    invoker = &memberFuncInvoker<X>;
  }
  //! @brief Clear delegate.
  void clear()
  {
    invoker = 0;
  }

  //! @brief Invoke delegate.
  Ret operator()(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, A13 a13) const
  {
    return invoker(this, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13);
  }

  //! @brief Returns @c true if delegate is empty, @c false otherwise.
  bool empty() const
  {
    return invoker == 0;
  }
  //! @brief Returns @c true if delegate is empty, @c false otherwise.
  bool operator!() const
  {
    return empty();
  }
private:
  struct SafeBoolStruct
  {
    int foo;
    freeFuncPtr nonzero;
  };
  typedef freeFuncPtr SafeBoolStruct::* unspecified_bool_type;
public:
  //! @brief Safe bool trick.
  operator unspecified_bool_type() const
  {
    return empty() ? 0 : &SafeBoolStruct::nonzero;
  }

  //! @brief Check for equality.
  friend bool operator==(const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13)>& lhs, const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13)>& rhs)
  {
    typedef delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13)> delegate;
    
    if(lhs.invoker == &delegate::staticFuncInvoker && rhs.invoker == &delegate::staticFuncInvoker)
      return lhs.staticFunction == rhs.staticFunction;
    else
      return lhs.pObj == rhs.pObj && lhs.function == rhs.function;
  }
  //! @brief Check for inequality
  friend bool operator!=(const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13)>& lhs, const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13)>& rhs)
  {
    return !(lhs == rhs);
  }

private:
  GenericClass* pObj;
  Ret (*invoker)(const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13)>*, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13);
  union
  {
    genericMemFn function;
    freeFuncPtr staticFunction;
  };

  static Ret staticFuncInvoker(const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13)>* pThis, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, A13 a13)
  {
    return pThis->staticFunction(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13);
  }

  template <typename T>
  static Ret memberFuncInvoker(const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13)>* pThis, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, A13 a13)
  {
    T* obj = reinterpret_cast<T*>(pThis->pObj);
    const void* tmp = &pThis->function;
    Ret (T::*mfp)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13) = *static_cast<Ret (T::* const*)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13)>(tmp);
    return (obj->*mfp)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13);
  }
};



template <typename Ret, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename A12, typename A13, typename A14>
class delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14)>
{
private:
  typedef Ret (*freeFuncPtr)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14);
  typedef Ret (GenericClass::*genericMemFn)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14);
public:
  typedef Ret result_type;

  //! @brief Create empty delegate.
  delegate()
  {
    clear();
  }
  //! @brief Bind free function.
  delegate(freeFuncPtr fn)
  {
    bind(fn);
  }
  //! @brief Bind non-const member function.
  template <typename X, typename Y>
  delegate(Y* obj, Ret (X::*fn)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14))
  {
    bind(obj, fn);
  }
  //! @brief Bind const member function.
  template <typename X, typename Y>
  delegate(const Y* obj, Ret (X::*fn)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14) const)
  {
    bind(obj, fn);
  }

  // Default copy constructor and assignment operator are fine.

  //! @brief Bind free function.
  delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14)>& operator=(freeFuncPtr fn)
  {
    bind(fn);
    return *this;
  }

  //! @brief Bind free function.
  void bind(freeFuncPtr fn)
  {
    staticFunction = fn;
    invoker = &staticFuncInvoker;
  }
  //! @brief Bind non-const member function.
  template <typename X, typename Y>
  void bind(Y* obj, Ret (X::*fn)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14))
  {
    pObj = reinterpret_cast<GenericClass*>(static_cast<X*>(obj));
    void* tmp = &function;
    *static_cast<Ret (X::**)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14)>(tmp) = fn;
    invoker = &memberFuncInvoker<X>;
  }
  //! @brief Bind const member function.
  template <typename X, typename Y>
  void bind(const Y* obj, Ret (X::*fn)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14) const)
  {
    pObj = const_cast<GenericClass*>(reinterpret_cast<const GenericClass*>(static_cast<const X*>(obj)));
    void* tmp = &function;
    *static_cast<Ret (X::**)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14) const>(tmp) = fn;
    invoker = &memberFuncInvoker<X>;
  }
  //! @brief Clear delegate.
  void clear()
  {
    invoker = 0;
  }

  //! @brief Invoke delegate.
  Ret operator()(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, A13 a13, A14 a14) const
  {
    return invoker(this, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14);
  }

  //! @brief Returns @c true if delegate is empty, @c false otherwise.
  bool empty() const
  {
    return invoker == 0;
  }
  //! @brief Returns @c true if delegate is empty, @c false otherwise.
  bool operator!() const
  {
    return empty();
  }
private:
  struct SafeBoolStruct
  {
    int foo;
    freeFuncPtr nonzero;
  };
  typedef freeFuncPtr SafeBoolStruct::* unspecified_bool_type;
public:
  //! @brief Safe bool trick.
  operator unspecified_bool_type() const
  {
    return empty() ? 0 : &SafeBoolStruct::nonzero;
  }

  //! @brief Check for equality.
  friend bool operator==(const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14)>& lhs, const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14)>& rhs)
  {
    typedef delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14)> delegate;
    
    if(lhs.invoker == &delegate::staticFuncInvoker && rhs.invoker == &delegate::staticFuncInvoker)
      return lhs.staticFunction == rhs.staticFunction;
    else
      return lhs.pObj == rhs.pObj && lhs.function == rhs.function;
  }
  //! @brief Check for inequality
  friend bool operator!=(const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14)>& lhs, const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14)>& rhs)
  {
    return !(lhs == rhs);
  }

private:
  GenericClass* pObj;
  Ret (*invoker)(const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14)>*, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14);
  union
  {
    genericMemFn function;
    freeFuncPtr staticFunction;
  };

  static Ret staticFuncInvoker(const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14)>* pThis, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, A13 a13, A14 a14)
  {
    return pThis->staticFunction(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14);
  }

  template <typename T>
  static Ret memberFuncInvoker(const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14)>* pThis, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, A13 a13, A14 a14)
  {
    T* obj = reinterpret_cast<T*>(pThis->pObj);
    const void* tmp = &pThis->function;
    Ret (T::*mfp)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14) = *static_cast<Ret (T::* const*)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14)>(tmp);
    return (obj->*mfp)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14);
  }
};



template <typename Ret, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename A12, typename A13, typename A14, typename A15>
class delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15)>
{
private:
  typedef Ret (*freeFuncPtr)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15);
  typedef Ret (GenericClass::*genericMemFn)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15);
public:
  typedef Ret result_type;

  //! @brief Create empty delegate.
  delegate()
  {
    clear();
  }
  //! @brief Bind free function.
  delegate(freeFuncPtr fn)
  {
    bind(fn);
  }
  //! @brief Bind non-const member function.
  template <typename X, typename Y>
  delegate(Y* obj, Ret (X::*fn)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15))
  {
    bind(obj, fn);
  }
  //! @brief Bind const member function.
  template <typename X, typename Y>
  delegate(const Y* obj, Ret (X::*fn)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15) const)
  {
    bind(obj, fn);
  }

  // Default copy constructor and assignment operator are fine.

  //! @brief Bind free function.
  delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15)>& operator=(freeFuncPtr fn)
  {
    bind(fn);
    return *this;
  }

  //! @brief Bind free function.
  void bind(freeFuncPtr fn)
  {
    staticFunction = fn;
    invoker = &staticFuncInvoker;
  }
  //! @brief Bind non-const member function.
  template <typename X, typename Y>
  void bind(Y* obj, Ret (X::*fn)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15))
  {
    pObj = reinterpret_cast<GenericClass*>(static_cast<X*>(obj));
    void* tmp = &function;
    *static_cast<Ret (X::**)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15)>(tmp) = fn;
    invoker = &memberFuncInvoker<X>;
  }
  //! @brief Bind const member function.
  template <typename X, typename Y>
  void bind(const Y* obj, Ret (X::*fn)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15) const)
  {
    pObj = const_cast<GenericClass*>(reinterpret_cast<const GenericClass*>(static_cast<const X*>(obj)));
    void* tmp = &function;
    *static_cast<Ret (X::**)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15) const>(tmp) = fn;
    invoker = &memberFuncInvoker<X>;
  }
  //! @brief Clear delegate.
  void clear()
  {
    invoker = 0;
  }

  //! @brief Invoke delegate.
  Ret operator()(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, A13 a13, A14 a14, A15 a15) const
  {
    return invoker(this, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15);
  }

  //! @brief Returns @c true if delegate is empty, @c false otherwise.
  bool empty() const
  {
    return invoker == 0;
  }
  //! @brief Returns @c true if delegate is empty, @c false otherwise.
  bool operator!() const
  {
    return empty();
  }
private:
  struct SafeBoolStruct
  {
    int foo;
    freeFuncPtr nonzero;
  };
  typedef freeFuncPtr SafeBoolStruct::* unspecified_bool_type;
public:
  //! @brief Safe bool trick.
  operator unspecified_bool_type() const
  {
    return empty() ? 0 : &SafeBoolStruct::nonzero;
  }

  //! @brief Check for equality.
  friend bool operator==(const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15)>& lhs, const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15)>& rhs)
  {
    typedef delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15)> delegate;
    
    if(lhs.invoker == &delegate::staticFuncInvoker && rhs.invoker == &delegate::staticFuncInvoker)
      return lhs.staticFunction == rhs.staticFunction;
    else
      return lhs.pObj == rhs.pObj && lhs.function == rhs.function;
  }
  //! @brief Check for inequality
  friend bool operator!=(const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15)>& lhs, const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15)>& rhs)
  {
    return !(lhs == rhs);
  }

private:
  GenericClass* pObj;
  Ret (*invoker)(const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15)>*, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15);
  union
  {
    genericMemFn function;
    freeFuncPtr staticFunction;
  };

  static Ret staticFuncInvoker(const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15)>* pThis, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, A13 a13, A14 a14, A15 a15)
  {
    return pThis->staticFunction(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15);
  }

  template <typename T>
  static Ret memberFuncInvoker(const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15)>* pThis, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, A13 a13, A14 a14, A15 a15)
  {
    T* obj = reinterpret_cast<T*>(pThis->pObj);
    const void* tmp = &pThis->function;
    Ret (T::*mfp)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15) = *static_cast<Ret (T::* const*)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15)>(tmp);
    return (obj->*mfp)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15);
  }
};



template <typename Ret, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename A12, typename A13, typename A14, typename A15, typename A16>
class delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16)>
{
private:
  typedef Ret (*freeFuncPtr)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16);
  typedef Ret (GenericClass::*genericMemFn)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16);
public:
  typedef Ret result_type;

  //! @brief Create empty delegate.
  delegate()
  {
    clear();
  }
  //! @brief Bind free function.
  delegate(freeFuncPtr fn)
  {
    bind(fn);
  }
  //! @brief Bind non-const member function.
  template <typename X, typename Y>
  delegate(Y* obj, Ret (X::*fn)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16))
  {
    bind(obj, fn);
  }
  //! @brief Bind const member function.
  template <typename X, typename Y>
  delegate(const Y* obj, Ret (X::*fn)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16) const)
  {
    bind(obj, fn);
  }

  // Default copy constructor and assignment operator are fine.

  //! @brief Bind free function.
  delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16)>& operator=(freeFuncPtr fn)
  {
    bind(fn);
    return *this;
  }

  //! @brief Bind free function.
  void bind(freeFuncPtr fn)
  {
    staticFunction = fn;
    invoker = &staticFuncInvoker;
  }
  //! @brief Bind non-const member function.
  template <typename X, typename Y>
  void bind(Y* obj, Ret (X::*fn)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16))
  {
    pObj = reinterpret_cast<GenericClass*>(static_cast<X*>(obj));
    void* tmp = &function;
    *static_cast<Ret (X::**)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16)>(tmp) = fn;
    invoker = &memberFuncInvoker<X>;
  }
  //! @brief Bind const member function.
  template <typename X, typename Y>
  void bind(const Y* obj, Ret (X::*fn)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16) const)
  {
    pObj = const_cast<GenericClass*>(reinterpret_cast<const GenericClass*>(static_cast<const X*>(obj)));
    void* tmp = &function;
    *static_cast<Ret (X::**)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16) const>(tmp) = fn;
    invoker = &memberFuncInvoker<X>;
  }
  //! @brief Clear delegate.
  void clear()
  {
    invoker = 0;
  }

  //! @brief Invoke delegate.
  Ret operator()(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, A13 a13, A14 a14, A15 a15, A16 a16) const
  {
    return invoker(this, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16);
  }

  //! @brief Returns @c true if delegate is empty, @c false otherwise.
  bool empty() const
  {
    return invoker == 0;
  }
  //! @brief Returns @c true if delegate is empty, @c false otherwise.
  bool operator!() const
  {
    return empty();
  }
private:
  struct SafeBoolStruct
  {
    int foo;
    freeFuncPtr nonzero;
  };
  typedef freeFuncPtr SafeBoolStruct::* unspecified_bool_type;
public:
  //! @brief Safe bool trick.
  operator unspecified_bool_type() const
  {
    return empty() ? 0 : &SafeBoolStruct::nonzero;
  }

  //! @brief Check for equality.
  friend bool operator==(const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16)>& lhs, const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16)>& rhs)
  {
    typedef delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16)> delegate;
    
    if(lhs.invoker == &delegate::staticFuncInvoker && rhs.invoker == &delegate::staticFuncInvoker)
      return lhs.staticFunction == rhs.staticFunction;
    else
      return lhs.pObj == rhs.pObj && lhs.function == rhs.function;
  }
  //! @brief Check for inequality
  friend bool operator!=(const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16)>& lhs, const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16)>& rhs)
  {
    return !(lhs == rhs);
  }

private:
  GenericClass* pObj;
  Ret (*invoker)(const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16)>*, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16);
  union
  {
    genericMemFn function;
    freeFuncPtr staticFunction;
  };

  static Ret staticFuncInvoker(const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16)>* pThis, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, A13 a13, A14 a14, A15 a15, A16 a16)
  {
    return pThis->staticFunction(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16);
  }

  template <typename T>
  static Ret memberFuncInvoker(const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16)>* pThis, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, A13 a13, A14 a14, A15 a15, A16 a16)
  {
    T* obj = reinterpret_cast<T*>(pThis->pObj);
    const void* tmp = &pThis->function;
    Ret (T::*mfp)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16) = *static_cast<Ret (T::* const*)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16)>(tmp);
    return (obj->*mfp)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16);
  }
};



template <typename Ret, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename A12, typename A13, typename A14, typename A15, typename A16, typename A17>
class delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17)>
{
private:
  typedef Ret (*freeFuncPtr)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17);
  typedef Ret (GenericClass::*genericMemFn)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17);
public:
  typedef Ret result_type;

  //! @brief Create empty delegate.
  delegate()
  {
    clear();
  }
  //! @brief Bind free function.
  delegate(freeFuncPtr fn)
  {
    bind(fn);
  }
  //! @brief Bind non-const member function.
  template <typename X, typename Y>
  delegate(Y* obj, Ret (X::*fn)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17))
  {
    bind(obj, fn);
  }
  //! @brief Bind const member function.
  template <typename X, typename Y>
  delegate(const Y* obj, Ret (X::*fn)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17) const)
  {
    bind(obj, fn);
  }

  // Default copy constructor and assignment operator are fine.

  //! @brief Bind free function.
  delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17)>& operator=(freeFuncPtr fn)
  {
    bind(fn);
    return *this;
  }

  //! @brief Bind free function.
  void bind(freeFuncPtr fn)
  {
    staticFunction = fn;
    invoker = &staticFuncInvoker;
  }
  //! @brief Bind non-const member function.
  template <typename X, typename Y>
  void bind(Y* obj, Ret (X::*fn)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17))
  {
    pObj = reinterpret_cast<GenericClass*>(static_cast<X*>(obj));
    void* tmp = &function;
    *static_cast<Ret (X::**)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17)>(tmp) = fn;
    invoker = &memberFuncInvoker<X>;
  }
  //! @brief Bind const member function.
  template <typename X, typename Y>
  void bind(const Y* obj, Ret (X::*fn)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17) const)
  {
    pObj = const_cast<GenericClass*>(reinterpret_cast<const GenericClass*>(static_cast<const X*>(obj)));
    void* tmp = &function;
    *static_cast<Ret (X::**)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17) const>(tmp) = fn;
    invoker = &memberFuncInvoker<X>;
  }
  //! @brief Clear delegate.
  void clear()
  {
    invoker = 0;
  }

  //! @brief Invoke delegate.
  Ret operator()(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, A13 a13, A14 a14, A15 a15, A16 a16, A17 a17) const
  {
    return invoker(this, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17);
  }

  //! @brief Returns @c true if delegate is empty, @c false otherwise.
  bool empty() const
  {
    return invoker == 0;
  }
  //! @brief Returns @c true if delegate is empty, @c false otherwise.
  bool operator!() const
  {
    return empty();
  }
private:
  struct SafeBoolStruct
  {
    int foo;
    freeFuncPtr nonzero;
  };
  typedef freeFuncPtr SafeBoolStruct::* unspecified_bool_type;
public:
  //! @brief Safe bool trick.
  operator unspecified_bool_type() const
  {
    return empty() ? 0 : &SafeBoolStruct::nonzero;
  }

  //! @brief Check for equality.
  friend bool operator==(const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17)>& lhs, const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17)>& rhs)
  {
    typedef delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17)> delegate;
    
    if(lhs.invoker == &delegate::staticFuncInvoker && rhs.invoker == &delegate::staticFuncInvoker)
      return lhs.staticFunction == rhs.staticFunction;
    else
      return lhs.pObj == rhs.pObj && lhs.function == rhs.function;
  }
  //! @brief Check for inequality
  friend bool operator!=(const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17)>& lhs, const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17)>& rhs)
  {
    return !(lhs == rhs);
  }

private:
  GenericClass* pObj;
  Ret (*invoker)(const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17)>*, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17);
  union
  {
    genericMemFn function;
    freeFuncPtr staticFunction;
  };

  static Ret staticFuncInvoker(const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17)>* pThis, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, A13 a13, A14 a14, A15 a15, A16 a16, A17 a17)
  {
    return pThis->staticFunction(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17);
  }

  template <typename T>
  static Ret memberFuncInvoker(const delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17)>* pThis, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, A13 a13, A14 a14, A15 a15, A16 a16, A17 a17)
  {
    T* obj = reinterpret_cast<T*>(pThis->pObj);
    const void* tmp = &pThis->function;
    Ret (T::*mfp)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17) = *static_cast<Ret (T::* const*)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17)>(tmp);
    return (obj->*mfp)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17);
  }
};

// ============================================================================
// [makeDelegate()]
// ============================================================================

template <typename X, typename Y, typename Ret>
delegate<Ret ()> makeDelegate(Y* obj, Ret (X::*mpf)())
{
  return delegate<Ret ()>(obj, mpf);
}

template <typename X, typename Y, typename Ret>
delegate<Ret ()> makeDelegate(const Y* obj, Ret (X::*mpf)() const)
{
  return delegate<Ret ()>(obj, mpf);
}


template <typename X, typename Y, typename Ret, typename A1>
delegate<Ret (A1)> makeDelegate(Y* obj, Ret (X::*mpf)(A1))
{
  return delegate<Ret (A1)>(obj, mpf);
}

template <typename X, typename Y, typename Ret, typename A1>
delegate<Ret (A1)> makeDelegate(const Y* obj, Ret (X::*mpf)(A1) const)
{
  return delegate<Ret (A1)>(obj, mpf);
}


template <typename X, typename Y, typename Ret, typename A1, typename A2>
delegate<Ret (A1, A2)> makeDelegate(Y* obj, Ret (X::*mpf)(A1, A2))
{
  return delegate<Ret (A1, A2)>(obj, mpf);
}

template <typename X, typename Y, typename Ret, typename A1, typename A2>
delegate<Ret (A1, A2)> makeDelegate(const Y* obj, Ret (X::*mpf)(A1, A2) const)
{
  return delegate<Ret (A1, A2)>(obj, mpf);
}


template <typename X, typename Y, typename Ret, typename A1, typename A2, typename A3>
delegate<Ret (A1, A2, A3)> makeDelegate(Y* obj, Ret (X::*mpf)(A1, A2, A3))
{
  return delegate<Ret (A1, A2, A3)>(obj, mpf);
}

template <typename X, typename Y, typename Ret, typename A1, typename A2, typename A3>
delegate<Ret (A1, A2, A3)> makeDelegate(const Y* obj, Ret (X::*mpf)(A1, A2, A3) const)
{
  return delegate<Ret (A1, A2, A3)>(obj, mpf);
}


template <typename X, typename Y, typename Ret, typename A1, typename A2, typename A3, typename A4>
delegate<Ret (A1, A2, A3, A4)> makeDelegate(Y* obj, Ret (X::*mpf)(A1, A2, A3, A4))
{
  return delegate<Ret (A1, A2, A3, A4)>(obj, mpf);
}

template <typename X, typename Y, typename Ret, typename A1, typename A2, typename A3, typename A4>
delegate<Ret (A1, A2, A3, A4)> makeDelegate(const Y* obj, Ret (X::*mpf)(A1, A2, A3, A4) const)
{
  return delegate<Ret (A1, A2, A3, A4)>(obj, mpf);
}


template <typename X, typename Y, typename Ret, typename A1, typename A2, typename A3, typename A4, typename A5>
delegate<Ret (A1, A2, A3, A4, A5)> makeDelegate(Y* obj, Ret (X::*mpf)(A1, A2, A3, A4, A5))
{
  return delegate<Ret (A1, A2, A3, A4, A5)>(obj, mpf);
}

template <typename X, typename Y, typename Ret, typename A1, typename A2, typename A3, typename A4, typename A5>
delegate<Ret (A1, A2, A3, A4, A5)> makeDelegate(const Y* obj, Ret (X::*mpf)(A1, A2, A3, A4, A5) const)
{
  return delegate<Ret (A1, A2, A3, A4, A5)>(obj, mpf);
}


template <typename X, typename Y, typename Ret, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6>
delegate<Ret (A1, A2, A3, A4, A5, A6)> makeDelegate(Y* obj, Ret (X::*mpf)(A1, A2, A3, A4, A5, A6))
{
  return delegate<Ret (A1, A2, A3, A4, A5, A6)>(obj, mpf);
}

template <typename X, typename Y, typename Ret, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6>
delegate<Ret (A1, A2, A3, A4, A5, A6)> makeDelegate(const Y* obj, Ret (X::*mpf)(A1, A2, A3, A4, A5, A6) const)
{
  return delegate<Ret (A1, A2, A3, A4, A5, A6)>(obj, mpf);
}


template <typename X, typename Y, typename Ret, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7>
delegate<Ret (A1, A2, A3, A4, A5, A6, A7)> makeDelegate(Y* obj, Ret (X::*mpf)(A1, A2, A3, A4, A5, A6, A7))
{
  return delegate<Ret (A1, A2, A3, A4, A5, A6, A7)>(obj, mpf);
}

template <typename X, typename Y, typename Ret, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7>
delegate<Ret (A1, A2, A3, A4, A5, A6, A7)> makeDelegate(const Y* obj, Ret (X::*mpf)(A1, A2, A3, A4, A5, A6, A7) const)
{
  return delegate<Ret (A1, A2, A3, A4, A5, A6, A7)>(obj, mpf);
}


template <typename X, typename Y, typename Ret, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8>
delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8)> makeDelegate(Y* obj, Ret (X::*mpf)(A1, A2, A3, A4, A5, A6, A7, A8))
{
  return delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8)>(obj, mpf);
}

template <typename X, typename Y, typename Ret, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8>
delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8)> makeDelegate(const Y* obj, Ret (X::*mpf)(A1, A2, A3, A4, A5, A6, A7, A8) const)
{
  return delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8)>(obj, mpf);
}


template <typename X, typename Y, typename Ret, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9>
delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9)> makeDelegate(Y* obj, Ret (X::*mpf)(A1, A2, A3, A4, A5, A6, A7, A8, A9))
{
  return delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9)>(obj, mpf);
}

template <typename X, typename Y, typename Ret, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9>
delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9)> makeDelegate(const Y* obj, Ret (X::*mpf)(A1, A2, A3, A4, A5, A6, A7, A8, A9) const)
{
  return delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9)>(obj, mpf);
}


template <typename X, typename Y, typename Ret, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10>
delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)> makeDelegate(Y* obj, Ret (X::*mpf)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10))
{
  return delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)>(obj, mpf);
}

template <typename X, typename Y, typename Ret, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10>
delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)> makeDelegate(const Y* obj, Ret (X::*mpf)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10) const)
{
  return delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)>(obj, mpf);
}


template <typename X, typename Y, typename Ret, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11>
delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11)> makeDelegate(Y* obj, Ret (X::*mpf)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11))
{
  return delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11)>(obj, mpf);
}

template <typename X, typename Y, typename Ret, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11>
delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11)> makeDelegate(const Y* obj, Ret (X::*mpf)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11) const)
{
  return delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11)>(obj, mpf);
}


template <typename X, typename Y, typename Ret, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename A12>
delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12)> makeDelegate(Y* obj, Ret (X::*mpf)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12))
{
  return delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12)>(obj, mpf);
}

template <typename X, typename Y, typename Ret, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename A12>
delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12)> makeDelegate(const Y* obj, Ret (X::*mpf)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12) const)
{
  return delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12)>(obj, mpf);
}


template <typename X, typename Y, typename Ret, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename A12, typename A13>
delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13)> makeDelegate(Y* obj, Ret (X::*mpf)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13))
{
  return delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13)>(obj, mpf);
}

template <typename X, typename Y, typename Ret, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename A12, typename A13>
delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13)> makeDelegate(const Y* obj, Ret (X::*mpf)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13) const)
{
  return delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13)>(obj, mpf);
}


template <typename X, typename Y, typename Ret, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename A12, typename A13, typename A14>
delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14)> makeDelegate(Y* obj, Ret (X::*mpf)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14))
{
  return delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14)>(obj, mpf);
}

template <typename X, typename Y, typename Ret, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename A12, typename A13, typename A14>
delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14)> makeDelegate(const Y* obj, Ret (X::*mpf)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14) const)
{
  return delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14)>(obj, mpf);
}


template <typename X, typename Y, typename Ret, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename A12, typename A13, typename A14, typename A15>
delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15)> makeDelegate(Y* obj, Ret (X::*mpf)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15))
{
  return delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15)>(obj, mpf);
}

template <typename X, typename Y, typename Ret, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename A12, typename A13, typename A14, typename A15>
delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15)> makeDelegate(const Y* obj, Ret (X::*mpf)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15) const)
{
  return delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15)>(obj, mpf);
}


template <typename X, typename Y, typename Ret, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename A12, typename A13, typename A14, typename A15, typename A16>
delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16)> makeDelegate(Y* obj, Ret (X::*mpf)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16))
{
  return delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16)>(obj, mpf);
}

template <typename X, typename Y, typename Ret, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename A12, typename A13, typename A14, typename A15, typename A16>
delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16)> makeDelegate(const Y* obj, Ret (X::*mpf)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16) const)
{
  return delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16)>(obj, mpf);
}


template <typename X, typename Y, typename Ret, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename A12, typename A13, typename A14, typename A15, typename A16, typename A17>
delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17)> makeDelegate(Y* obj, Ret (X::*mpf)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17))
{
  return delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17)>(obj, mpf);
}

template <typename X, typename Y, typename Ret, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename A12, typename A13, typename A14, typename A15, typename A16, typename A17>
delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17)> makeDelegate(const Y* obj, Ret (X::*mpf)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17) const)
{
  return delegate<Ret (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17)>(obj, mpf);
}

}

#endif
